package com.cq.hd.admin.biz;

import com.cq.hd.admin.po.TbBusinessAdminUserPo;
import com.cq.hd.admin.vo.AdminBusinessSubsidyVo;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.common.utils.StringUtils;
import com.cq.hd.member.api.TbBankPayRecordApi;
import com.cq.hd.member.api.TbBusinessApi;
import com.cq.hd.member.api.dto.BankPayRechargeDto;
import com.cq.hd.member.api.vo.BankPayRechargeVo;
import com.cq.hd.member.api.vo.BusinessVo;
import com.cq.hd.order.api.TbOrderApi;
import com.cq.hd.order.api.TbOrderItemApi;
import com.cq.hd.order.api.TbOrderSettleBillApi;
import com.cq.hd.order.api.dto.OrderDto;
import com.cq.hd.order.api.dto.OrderItemDto;
import com.cq.hd.order.api.dto.OrderSettleBillDto;
import com.cq.hd.order.api.vo.OrderItemVo;
import com.cq.hd.order.api.vo.OrderSettleBillVo;
import com.cq.hd.order.api.vo.OrderVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class AdminBusinessSubsidyBiz {

    @Autowired
    private TbBusinessApi businessApi;

    @Autowired
    private TbOrderApi orderApi;

    @Autowired
    private TbOrderItemApi orderItemApi;

    @Autowired
    private TbOrderSettleBillApi orderSettleBillApi;

    @Autowired
    private TbBankPayRecordApi bankPayRecordApi;

    public AdminBusinessSubsidyVo preRecharge(TbBusinessAdminUserPo businessAdminUserPo) {
        Long businessId = businessAdminUserPo.getBusinessId();
        BusinessVo businessVo = businessApi.getActiveCount(businessAdminUserPo.getAppUserId(), businessId).unpack();
        if (businessVo == null) {
            Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
        }

        // 补贴账户余额
        BigDecimal subsidyAmt = businessVo.getSubsidyAmt();
        // 待充值=已结算待打款的补贴金额-补贴账户余额=已结算的订单的总补贴金额-当前补贴账户金额=已结算的订单的订单补贴金额+红包金额-当前补贴账户金额
        BigDecimal waitRechargeAmt = BigDecimal.ZERO;
        // 本月待结算=本月已核销订单，需要补贴给商户的金额
        BigDecimal monthWaitSettleAmt = BigDecimal.ZERO;
        // 上月结算=上个自然月实际结算打款给商户的补贴金额
        BigDecimal lastMonthSettleAmt = BigDecimal.ZERO;
        // 服务费金额=待充值金额*2%
        BigDecimal feeAmt = BigDecimal.ZERO;
        // 发票税点金额=待充值金额*6%
        BigDecimal invoiceAmt = BigDecimal.ZERO;
        // 合计待充金额=待充值金额+服务费金额+发票税点金额
        BigDecimal totalWaitRechargeAmt = BigDecimal.ZERO;

        LocalDate nowLocalDate = LocalDate.now();
        // 本月1号
        LocalDate firstDayOfMonth = nowLocalDate.with(TemporalAdjusters.firstDayOfMonth());
        String firstDayOfMonthStr = LocalDateUtil.toLocalDateToString(firstDayOfMonth, Constant.YYYY_MM_DD) + " 00:00:00";
        String lastDayOfMonthEndStr = LocalDateUtil.toLocalDateToString(nowLocalDate.with(TemporalAdjusters.lastDayOfMonth()), Constant.YYYY_MM_DD) + " 23:59:59";
        // 本月最后一天
        LocalDateTime firstDayOfMonthStart = LocalDateUtil.toLocalDateTime(firstDayOfMonthStr, Constant.YYYY_MM_DD_HH_MM_SS);
        LocalDateTime lastDayOfMonthEnd = LocalDateUtil.toLocalDateTime(lastDayOfMonthEndStr, Constant.YYYY_MM_DD_HH_MM_SS);

        // 查询待支付/支付失败的商品补贴的订单结算数据
        OrderSettleBillDto orderSettleBillDto = new OrderSettleBillDto();
        orderSettleBillDto.setBusinessId(businessId);
        orderSettleBillDto.setTradeType(OrderSettleBillTradeTypeEnum.SUBSIDY_AMT.getValue());
        orderSettleBillDto.setTradeStates(Arrays.asList(OrderSettleBillTradeStateEnum.WAIT.getValue(), OrderSettleBillTradeStateEnum.FAIL.getValue()));
        List<OrderSettleBillVo> orderSettleBillVos = orderSettleBillApi.listByDto(orderSettleBillDto).unpack();
        if (!CollectionUtils.isEmpty(orderSettleBillVos)) {
            for (OrderSettleBillVo orderSettleBillVo : orderSettleBillVos) {
                LocalDateTime tradeTime = orderSettleBillVo.getTradeTime();
                if (tradeTime.compareTo(firstDayOfMonthStart) >= 0 && tradeTime.compareTo(lastDayOfMonthEnd) <= 0) {
                        monthWaitSettleAmt = monthWaitSettleAmt.add(orderSettleBillVo.getTradeAmt());
                }
                waitRechargeAmt = waitRechargeAmt.add(orderSettleBillVo.getTradeAmt());
            }
        }

        // 根据商家id查询本月待结算(已核销)的的订单,累加总补贴金额
        OrderDto orderDto = new OrderDto();
        orderDto.setBusinessId(businessId);
        orderDto.setOrderStates(Collections.singletonList(OrderStateEnum.VERIFIED.getValue()));
        List<OrderVo> orderVos = orderApi.listByDto(orderDto).unpack();
        if (!CollectionUtils.isEmpty(orderVos)) {
            List<Long> orderIds = orderVos.stream().map(OrderVo::getId).collect(Collectors.toList());
            OrderItemDto orderItemDto = new OrderItemDto();
            orderItemDto.setOrderIds(orderIds);
            orderItemDto.setSubOrderStates(Collections.singletonList(SubOrderStateEnum.VERIFIED.getValue()));
            orderItemDto.setStartVerifyTime(firstDayOfMonthStr);
            orderItemDto.setEndVerifyTime(lastDayOfMonthEndStr);
            List<OrderItemVo> orderItemVos = orderItemApi.listByDto(orderItemDto).unpack();
            if (!CollectionUtils.isEmpty(orderItemVos)) {
                for (OrderItemVo orderItemVo : orderItemVos) {
                    monthWaitSettleAmt = monthWaitSettleAmt.add(orderItemVo.getTotalSubsidyAmt());
                }
            }
        }

        // 根据商家id+上月查询实际结算的补贴金额
        LocalDate lastMonthLocalDate = nowLocalDate.plusMonths(-1);
        // 上月1号
        LocalDate firstDayOfLastMonth = lastMonthLocalDate.with(TemporalAdjusters.firstDayOfMonth());
        // 上月最后一天
        LocalDate lastDayOfLastMonth = lastMonthLocalDate.with(TemporalAdjusters.lastDayOfMonth());
        String firstDayOfLastMonthStartStr = LocalDateUtil.toLocalDateToString(firstDayOfLastMonth, Constant.YYYY_MM_DD) + " 00:00:00";
        String lastDayOfLastMonthEndStr = LocalDateUtil.toLocalDateToString(lastDayOfLastMonth, Constant.YYYY_MM_DD) + " 23:59:59";

        orderSettleBillDto = new OrderSettleBillDto();
        orderSettleBillDto.setBusinessId(businessId);
        orderSettleBillDto.setTradeType(OrderSettleBillTradeTypeEnum.SUBSIDY_AMT.getValue());
        orderSettleBillDto.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
        orderSettleBillDto.setStartTradeTime(firstDayOfLastMonthStartStr);
        orderSettleBillDto.setEndTradeTime(lastDayOfLastMonthEndStr);
        orderSettleBillVos = orderSettleBillApi.listByDto(orderSettleBillDto).unpack();
        if (!CollectionUtils.isEmpty(orderSettleBillVos)) {
            for (OrderSettleBillVo orderSettleBillVo : orderSettleBillVos) {
                lastMonthSettleAmt = lastMonthSettleAmt.add(orderSettleBillVo.getTradeAmt());
            }
        }

        waitRechargeAmt = waitRechargeAmt.subtract(subsidyAmt).max(BigDecimal.ZERO);
        if (waitRechargeAmt.compareTo(BigDecimal.ZERO) > 0) {
            // 保留两位，舍去第三位
            feeAmt = waitRechargeAmt.multiply(Constant.BANK_PAY_FEE_AMT_RATE).setScale(2, BigDecimal.ROUND_DOWN);
            invoiceAmt = waitRechargeAmt.multiply(Constant.BANK_PAY_INVOICE_AMT_RATE).setScale(2, BigDecimal.ROUND_DOWN);
            totalWaitRechargeAmt = waitRechargeAmt.add(feeAmt).add(invoiceAmt).setScale(2, BigDecimal.ROUND_DOWN);
        }

        AdminBusinessSubsidyVo adminBusinessSubsidyVo = new AdminBusinessSubsidyVo();
        adminBusinessSubsidyVo.setSubsidyAmt(subsidyAmt);
        adminBusinessSubsidyVo.setWaitRechargeAmt(waitRechargeAmt);
        adminBusinessSubsidyVo.setMonthWaitSettleAmt(monthWaitSettleAmt);
        adminBusinessSubsidyVo.setLastMonthSettleAmt(lastMonthSettleAmt);
        adminBusinessSubsidyVo.setFeeAmt(feeAmt);
        adminBusinessSubsidyVo.setInvoiceAmt(invoiceAmt);
        adminBusinessSubsidyVo.setTotalWaitRechargeAmt(totalWaitRechargeAmt);
        adminBusinessSubsidyVo.setBankFeeAmt(Constant.BANK_PAY_AMT);

        return adminBusinessSubsidyVo;
    }

    public BankPayRechargeVo recharge(BankPayRechargeDto bankPayRechargeDto) {
        BigDecimal rechargeAmt = bankPayRechargeDto.getRechargeAmt();
        if (rechargeAmt == null || rechargeAmt.compareTo(new BigDecimal("1")) < 0) {
            Throw.isBusinessException("充值金额需大于1元");
        }
        rechargeAmt = rechargeAmt.setScale(2, BigDecimal.ROUND_DOWN);

        // 调用hf网银支付接口，如果成功，添加网银支付记录，否则返回错误
        BankPayRechargeVo bankPayRechargeVo = bankPayRecordApi.recharge(bankPayRechargeDto).unpack();
        if (bankPayRechargeVo == null || StringUtils.isBlank(bankPayRechargeVo.getFromUrl())) {
            log.error("网银充值补贴金失败，获取网银跳转链接数据为空，businessId：{}，rechargeAmt：{}", bankPayRechargeDto.getBusinessId(), rechargeAmt);
            Throw.isBusinessException("充值失败，请联系客服");
        }

        return bankPayRechargeVo;
    }

}
